import 'dart:async';
import 'dart:io';

import 'package:aero_frisbee/core/extension/string_ext.dart';
import 'package:aero_frisbee/pages/modues/message/pages/message/message_detail/viwe_model/af_bottom_input_field_view_model.dart';
import 'package:audio_waveforms/audio_waveforms.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:path_provider/path_provider.dart';

import 'af_input_record_indicator_view.dart';

class AfInputContentRecordView extends ConsumerStatefulWidget {
  const AfInputContentRecordView({
    Key? key,
    required this.onRecorderEnd,
  }) : super(key: key);

  final void Function(String? path, int? duration) onRecorderEnd;

  @override
  ConsumerState<AfInputContentRecordView> createState() =>
      _AfInputContentRecordViewState();
}

class _AfInputContentRecordViewState
    extends ConsumerState<AfInputContentRecordView> {
  OverlayEntry? _overlayEntry;

  RecorderController? _recorderController;

  bool _hasPermission = false;

  @override
  Widget build(BuildContext context) {
    final _ = ref.watch(afRecordTypeStateServiceProvider);
    return GestureDetector(
      behavior: HitTestBehavior.deferToChild,
      onLongPressDown: (details) {
        if (!_hasPermission) {
          _getPermission();
        }
      },
      onLongPressStart: (details) async {
        if (_hasPermission) {
          _startRecorder(
            details: details,
          );
        } else {
          "You have not authorised this permission.".toast();
        }
      },
      onLongPressEnd: (details) {
        if (_hasPermission) {
          _stopRecorder(
            details: details,
          );
        }
      },
      onLongPressMoveUpdate: (details) {
        var longPressOffset = details.globalPosition;
        ref
            .read(recordLongPressMoveOffsetServiceProvider.notifier)
            .update(longPressOffset);
      },
      child: Container(
        decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(4.0),
          color: const Color(0xFFffffff),
        ),
        child: const Center(
          child: Text(
            'Hold to talk',
            style: TextStyle(
              color: Color(0xff202020),
              fontWeight: FontWeight.w500,
              fontSize: 12,
            ),
          ),
        ),
      ),
    );
  }

  void _getPermission() async {
    var p = await _recorderController?.checkPermission();
    _hasPermission = p ?? false;
  }

  _buildOverLayView(BuildContext context) {
    if (_overlayEntry == null) {
      _overlayEntry = OverlayEntry(
        builder: (context) {
          return const AfInputRecordIndicatorView();
        },
      );
      Overlay.of(context).insert(_overlayEntry!);
    }
  }

  _hideVoiceView() async {
    if (_overlayEntry != null) {
      _overlayEntry?.remove();
      _overlayEntry?.dispose();
      _overlayEntry = null;
    }
  }

  void _startRecorder({required LongPressStartDetails details}) async {
    try {
      var path = '';
      var tempDir = await getTemporaryDirectory();
      String voiceDir = '${tempDir.path}/medias/voice/';
      if (!(await Directory(voiceDir).exists())) {
        await Directory(voiceDir).create(recursive: true);
      }
      path = '$voiceDir${DateTime.now().millisecondsSinceEpoch}.m4a';
      await _recorderController?.record(
        path: path,
        sampleRate: 44100,
        bitRate: 48000,
      );

      ///开始录制
      ref.read(afRecordTypeStateServiceProvider.notifier).record();
      // ignore: use_build_context_synchronously
      _buildOverLayView(context);
    } catch (err) {
      debugPrint('startRecorder error: ${err.toString()}');
      _stopRecorder(
        details: LongPressEndDetails(globalPosition: details.globalPosition),
      );
    }
  }

  Future<void> _stopRecorder({required LongPressEndDetails details}) async {
    try {
      var path = await _recorderController?.stop();
      final inCancel = ref.read(afRecordTypeStateServiceProvider).maybeWhen(
            recordCancel: () => true,
            orElse: () => false,
          );
      if (!inCancel) {
        if ((_recorderController?.recordedDuration.inSeconds ?? 0) > 1) {
          widget.onRecorderEnd(
            path,
            _recorderController?.recordedDuration.inSeconds,
          );
        } else {
          "The recording time is no less than 1s".toast();
        }
      }
    } on Exception catch (err) {
      debugPrint('stopRecorder error: $err');
    }
    _hideVoiceView();
  }

  @override
  void initState() {
    _recorderController = RecorderController();

    super.initState();
  }

  @override
  void dispose() {
    _overlayEntry?.remove();
    _overlayEntry?.dispose();
    _overlayEntry = null;

    _recorderController?.dispose();
    _recorderController = null;

    super.dispose();
  }
}
